#include "Server.h"


//最多处理的connect
#define MAX_EVENTS 1000
//事件数组
struct epoll_event eventList[MAX_EVENTS];
//epoll描述符
int epollfd;

//构造函数
server::server(int port,string ip):server_port(port),server_ip(ip){}

//析构函数
server::~server(){
    for(auto conn: sock_arr)
        close(conn);
    close(server_sockfd);
}

//服务器开始服务
void server::run()
{
    //定义sockfd
    server_sockfd = socket(AF_INET,SOCK_STREAM, 0);

    //定义sockaddr_in
    struct sockaddr_in server_sockaddr;
    server_sockaddr.sin_family = AF_INET;//TCP/IP协议族
    server_sockaddr.sin_port = htons(server_port);//server_port;//端口号
    server_sockaddr.sin_addr.s_addr = inet_addr(server_ip.c_str());//ip地址，127.0.0.1是环回地址，相当于本机ip

    //bind，成功返回0，出错返回-1
    if(bind(server_sockfd,(struct sockaddr *)&server_sockaddr,sizeof(server_sockaddr))==-1)
    {
        perror("bind");//输出错误原因
        exit(1);//结束程序
    }

    //listen，成功返回0，出错返回-1
    if(listen(server_sockfd,20) == -1)
    {
        perror("listen");//输出错误原因
        exit(1);//结束程序
    }
    
    // epoll 初始化
    epollfd = epoll_create(MAX_EVENTS);
    struct epoll_event event;
    event.events = EPOLLIN | EPOLLET;
    event.data.fd = server_sockfd;
    
    //add Event
    if(epoll_ctl(epollfd, EPOLL_CTL_ADD, server_sockfd, &event) < 0)
    {
        printf("epoll add fail : fd = %d\n", server_sockfd);
        return;
    }
     //epoll
    while(1)
    {
        int timeout = 3000;                
        //epoll_wait
        int ret = epoll_wait(epollfd, eventList, MAX_EVENTS, timeout);
        
        if(ret < 0)
        {
            printf("epoll error\n");
            break;
        }
        else if(ret == 0)
        {
            printf("timeout ...\n");
            continue;
        }
        
        //直接获取了事件数量,给出了活动的流,这里是和poll区别的关键
        int i = 0;
        for(i = 0; i < ret; i++) {
            // 错误退出
            if ((eventList[i].events & EPOLLERR) ||
                (eventList[i].events & EPOLLHUP) ||
                !(eventList[i].events & EPOLLIN))
            {
                printf ( "epoll error\n");
                close (eventList[i].data.fd);
                continue;
            }
            
            // 新客户端
            if (eventList[i].data.fd == server_sockfd)
            {
                struct sockaddr_in sin;
                socklen_t len = sizeof(struct sockaddr_in);
                bzero(&sin, len);
            
                int confd = accept(server_sockfd, (struct sockaddr*)&sin, &len);
            
                if (confd < 0) {
                    printf("bad accept\n");
                    continue;
                } else {
                    printf("New Connection: %d\n", confd);
                }
                // 将新建立的连接添加到 EPOLL 的监听中
                struct epoll_event event;
                event.data.fd = confd;
                event.events =  EPOLLIN | EPOLLET;
                epoll_ctl(epollfd, EPOLL_CTL_ADD, confd, &event);
            }

            // 接收客户端消息
            else {
                RecvMsg(eventList[i].data.fd);
            }
        }
    }
}

//子线程工作的静态函数
//注意，前面不用加static，否则会编译报错
void server::RecvMsg(int conn)
{
    //接收缓冲区
    char buffer[1000];
    // memset(buffer,0, sizeof(buffer));
    // int len = recv(conn, buffer, sizeof(buffer),0);
    LoginInfo info;
    memset(&info, 0, sizeof(info));
    int len = recv(conn, (void*)&info, sizeof(info), 0);
    cout << "name: " << info.name << ", passwd: " << info.passwd << endl;
    // cout<<"收到套接字描述符为"<<conn<<"发来的信息："<<buffer<<endl;

    // 将接收到的数据发送回去
    len=send(conn, "OK", strlen(buffer), 0);
}
